package com.qfjy.util.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * Redis解决高并发（重复提交） 幂等性
 */
@Component
public class RedisRepeatUtils {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Resource(name = "redisTemplate")
    ValueOperations<String,String> string;

    /**Redis解决重复提交 token过期时间  单位（分钟）*/
    private static Integer REDIS_TOKEN_REPEAT_TIMEOUT_MINUTES=30;

    /**
     * TODO Redis生成 token key
     *   1、生成key存入redis  并设置过期时间（大厂都是30分钟）
     *   2、传递到前端页面（隐藏域）
     * key生成规则：
     *   token:业务逻辑方法:唯一标识值uuid
     *   uuid：理论上全球唯一标识值
     *
     * @param request  请求对象
     * @param key  命令规则 前缀 业务逻辑方法
     */
    public void generatorToken(HttpServletRequest request,String key){
        String uuid= UUID.randomUUID().toString();
        //String key="token:importExcel:"+uuid;
        key=key+uuid;
        string.set(key,uuid,REDIS_TOKEN_REPEAT_TIMEOUT_MINUTES, TimeUnit.MINUTES);
        request.setAttribute("token",uuid);
    }

    /**
     * TODO Redis解决高并发重复提交  校验
     * 校验逻辑：高并发情况下：非幂等性
     * 1、Redis key 和 前端隐藏域中的token进行比较
     *   如果相等 （Redis key删除） 即执行业务逻辑
     *   如果不相等--》本次提交，不执行。
     * @param request  请求对象
     * @param key  命令规则 前缀 业务逻辑方法
     * @return boolean (flase 比较失败不相等）(true相等）
     */
    public boolean validateToken(HttpServletRequest request,String key){

        String tokenWeb=request.getParameter("token");
        //Redis key命名规范：
         key=key+tokenWeb;
        String tokenRedis= string.get(key);
        redisTemplate.delete(key);
        return tokenWeb.equals(tokenRedis);
    }

}
